package cn.csg.iotplatform.module.system.api.deviceno;

import cn.csg.iotplatform.framework.common.pojo.CommonResult;
import cn.csg.iotplatform.framework.common.util.object.ObjectUtils;
import cn.csg.iotplatform.module.system.api.deviceno.dto.DeviceNoDTO;
import cn.csg.iotplatform.module.system.api.deviceno.dto.DeviceNoSaveDTO;
import cn.csg.iotplatform.module.system.api.deviceno.dto.ModelDeleteVO;
import cn.csg.iotplatform.module.system.api.deviceno.dto.ModelVO;
import cn.csg.iotplatform.module.system.api.file.dto.EqtFileDeleteVO;
import cn.csg.iotplatform.module.system.api.manufacturer.dto.EqtManufactureDto;
import cn.csg.iotplatform.module.system.controller.admin.file.vo.EqtFileSaveVO;
import cn.csg.iotplatform.module.system.dal.dataobject.dvattachment.DvAttachmentDO;
import cn.csg.iotplatform.module.system.dal.dataobject.logger.GkDeviceCenterApiLogDO;
import cn.csg.iotplatform.module.system.dal.dataobject.manufacturer.ManufacturerDO;
import cn.csg.iotplatform.module.system.dal.mysql.dvattachment.DvAttachmentMapper;
import cn.csg.iotplatform.module.system.enums.AttachmentTypeEnum;
import cn.csg.iotplatform.module.system.enums.DeviceCenterApiEnum;
import cn.csg.iotplatform.module.system.service.eqfile.DvAttachmentService;
import cn.csg.iotplatform.module.system.service.eqfile.EqtFileService;
import cn.csg.iotplatform.module.system.service.logger.GkDeviceCenterApiLogService;
import cn.csg.iotplatform.module.system.util.EqtCenterUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.dtflys.forest.http.ForestResponse;
import com.dtflys.forest.http.HttpStatus;
import dm.jdbc.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import netscape.javascript.JSObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static cn.csg.iotplatform.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * @author Clqv
 * @create 2024--11--13 15:05
 */
@RestController // 提供 RESTful API 接口，给 Feign 调用
@Validated
@Slf4j
public class DeviceNoApiImpl implements DeviceNoApi{

    @Resource
    private EqtDeviceNoClient eqtDeviceNoClient;

    @Resource
    private EqtFileService eqtFileService;

    @Value("${iot.eqt-center.bureauCode}")
    private String bureauCode;

    @Resource
    private GkDeviceCenterApiLogService gkDeviceCenterApiLogService;

    @Resource
    private DvAttachmentMapper attachmentMapper;

    @Resource
    private DvAttachmentService dvAttachmentService;

    @Value("${iot.eqt-center.url}")
    public String gkUrl;


    @Override
    public CommonResult<Boolean> syncDeleteEqtDeviceModel(List<String> ids) {
        //先将表单同步至设备中心，获取表单id
        for(String id : ids) {
            ModelDeleteVO modelDeleteVO = ModelDeleteVO.builder().specifyModelId(id).build();
            syncDeleteDeviceNoData(modelDeleteVO);
        }
        return CommonResult.success(true);
    }

    @Override
    public CommonResult<JSONObject> syncSaveEqtDeviceModel(DeviceNoSaveDTO deviceNoSaveDTO) {

        //先将表单同步至设备中心，获取表单id
        ModelVO modelVO = BeanUtil.toBean(deviceNoSaveDTO, ModelVO.class);

        //设置局编码
        modelVO.setBureauCode( bureauCode );

        //设置创建人和修改人
        modelVO.setCreatorId( deviceNoSaveDTO.getCreator() );
        modelVO.setUpdaterId( deviceNoSaveDTO.getUpdater() );

        JSONObject result = syncDeviceNoData(modelVO);
        if (ObjectUtil.isNotEmpty( result )){
            //如果为新增则从设备中心返回的结果中取到业务id，修改则直接取门户本地的id
            String id = StringUtils.isEmpty( deviceNoSaveDTO.getId() ) ? result.getString("data") : deviceNoSaveDTO.getId();


            // syncWlFile( id, deviceNoSaveDTO.getFileUrlList() );
            //备份物联文件
            List<String> fileUrlList = deviceNoSaveDTO.getFileUrlList();
            try {

                List<String> insertFileUrlList = deviceNoSaveDTO.getInsertFileUrlList();
                if (CollectionUtil.isNotEmpty( insertFileUrlList )){
                    syncFile( insertFileUrlList, id );
                }

                List<String> deletedFileIdList = deviceNoSaveDTO.getDeletedFileIdList();
                if ( CollectionUtil.isNotEmpty( deletedFileIdList ) ){
                    syncDeleteFile( deletedFileIdList, id );
                }

                //正常备份物联附件，type为 0
                syncWlFile( id, fileUrlList, 0 );
            }catch ( Exception e ){
                //异常备份物联附件，type为 1
                syncWlFile( id, fileUrlList, 1 );
            }
        }
        return CommonResult.success( result );
    }

    /**
     * 初始化同步终端型号的附件
     * @param deviceNoDTOS
     * @return
     */
    @Override
    public CommonResult<JSONObject> initSyncDeviceNoFile(List<DeviceNoDTO> deviceNoDTOS) {

        log.info( "初始化同步终端型号的附件开始--------------------------------------------" );
        if ( CollectionUtil.isNotEmpty( deviceNoDTOS ) ){


            for (DeviceNoDTO deviceNoDTO : deviceNoDTOS) {

                //新增接口不需要比对，直接同步即可
                String devicePicture = deviceNoDTO.getDevicePicture();
                JSONArray pictureUrls = JSONArray.parseArray( devicePicture );
                List<String> insertFileUrlList = new ArrayList<>();
                for (int i = 0;  i > pictureUrls.size(); i++){
                    String url = pictureUrls.getString(i);
                    insertFileUrlList.add( url );
                }
                syncFile(insertFileUrlList, deviceNoDTO.getId());
            }
        }
        log.info( "初始化同步终端型号的附件完成--------------------------------------------" );
        return CommonResult.success( null );
    }

    public JSONObject syncDeviceNoData(ModelVO modelVO){

        //插入日志
        GkDeviceCenterApiLogDO gkDeviceCenterApiLogDO = new GkDeviceCenterApiLogDO();
        gkDeviceCenterApiLogDO.setRequestParam( JSONObject.toJSONString( modelVO ) );
        // 终端型号进行一次同步任务
        ForestResponse<JSONObject> response = eqtDeviceNoClient.saveEqtDeviceModel(EqtCenterUtil.doPostJsonHeader(JSON.toJSONString(modelVO)), modelVO);
        log.info("终端型号同步共库返回信息{},{},{}", response.getException(), response.getContent(), response.getResult());
        if ( !response.isSuccess() ){
            gkDeviceCenterApiLogDO.setStatusCode( response.statusCode() + "" );
            gkDeviceCenterApiLogDO.setResponseResult( response.getContent() );
            gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.SAVEEQTDEVICEMODEL );
            throw exception("调用设备中心保存/更新接口失败：" + response.getContent() );
        }
        if ( (response.getResult().get("code") != null && !response.getResult().get("code").toString().equals("200")) ){
            gkDeviceCenterApiLogDO.setStatusCode( response.getResult().get("code") + "" );
            gkDeviceCenterApiLogDO.setResponseResult( response.getResult().toJSONString() );
            gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.SAVEEQTDEVICEMODEL );
            throw exception("调用设备中心保存/更新接口失败：" + (response.getResult().get("msg") != null ? response.getResult().get("msg").toString() : ""));
        }

        gkDeviceCenterApiLogDO.setStatusCode( response.statusCode() + "" );
        gkDeviceCenterApiLogDO.setResponseResult( response.getResult().toJSONString() );
        gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.SAVEEQTDEVICEMODEL );

        return response.getResult();
    }

    public JSONObject syncDeleteDeviceNoData(ModelDeleteVO modelVO){

        //插入日志
        GkDeviceCenterApiLogDO gkDeviceCenterApiLogDO = new GkDeviceCenterApiLogDO();
        gkDeviceCenterApiLogDO.setRequestParam( JSONObject.toJSONString( modelVO ) );

        // 型号删除同步任务
        ForestResponse<JSONObject> response = eqtDeviceNoClient.deleteEqtDeviceModel(EqtCenterUtil.doPostJsonHeader(JSON.toJSONString(modelVO)), modelVO);
        log.info("终端型号同步删除共库返回信息{},{},{}", response.getException(), response.getContent(), response.getResult());
        if ( !response.isSuccess() ){
            gkDeviceCenterApiLogDO.setStatusCode( response.statusCode() + "" );
            gkDeviceCenterApiLogDO.setResponseResult( response.getContent() );
            gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.DELETEEQTDEVICEMODEL );
            throw exception("调用设备中心删除接口失败：" + response.getContent() );
        }
        if ( (response.getResult().get("code") != null && !response.getResult().get("code").toString().equals("200")) ){
            gkDeviceCenterApiLogDO.setStatusCode( response.getResult().get("code") + "" );
            gkDeviceCenterApiLogDO.setResponseResult( response.getResult().toJSONString() );
            gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.DELETEEQTDEVICEMODEL );
            throw exception("调用设备中心删除接口失败：" + (response.getResult().get("msg") != null ? response.getResult().get("msg").toString() : ""));
        }
        gkDeviceCenterApiLogDO.setStatusCode( response.statusCode() + "" );
        gkDeviceCenterApiLogDO.setResponseResult( response.getResult().toJSONString() );
        gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.DELETEEQTDEVICEMODEL );

        return response.getResult();
    }


    private void syncFile(List<String> insertFileUrls, String objectId) {

        //先全部删除物联门户的附件备份
        attachmentMapper.deleteByFlagId( objectId );

        for (String insertFileUrl : insertFileUrls) {

            EqtFileSaveVO eqtFileSaveVO = new EqtFileSaveVO();
            eqtFileSaveVO.setObjectId(objectId);
            eqtFileSaveVO.setFlag("2");
            eqtFileSaveVO.setJobTypeCode(AttachmentTypeEnum.devicePicture.name());
            eqtFileSaveVO.setFileUrl( insertFileUrl );

            eqtFileService.syncFile(eqtFileSaveVO);
        }
    }

    private void syncDeleteFile(List<String> deletedFileIds, String objectId) {

        for (String fileId : deletedFileIds) {

            EqtFileDeleteVO eqtFileDeleteVO = new EqtFileDeleteVO();
            eqtFileDeleteVO.setObjectId( objectId );
            eqtFileDeleteVO.setAttachmentId( fileId );
            eqtFileDeleteVO.setJobTypeCode( AttachmentTypeEnum.devicePicture.name() );

            eqtFileService.syncDeleteFile( eqtFileDeleteVO );
        }
    }

    /**
     *
     * 附件备份到物联本地
     */
    private void syncWlFile(String deviceNoId, List<String> fileUrls, Integer type) {
        try {
            for (String fileUrl : fileUrls) {
                log.info("正在备份物联附件，fileUrl-->{}", fileUrl);

                //直接用路径先从设备中心附件表中获取门户的minio_url，获取不到则可能是页面重新新增的附件
                String iotUrl = attachmentMapper.getFileByUrl(deviceNoId, fileUrl);
                if (StringUtil.isNotEmpty( iotUrl )){

                    log.info("正在重新备份已同步的物联附件，iotUrl-->{}", iotUrl);
                    //找得到证明之前这个附件已经同步成功，直接之前的minio路径重新备份即可
                    dvAttachmentService.syncWlFile( deviceNoId, AttachmentTypeEnum.devicePicture.name(), iotUrl, null, type );
                }else {
                    log.info("正在备份新增的物联附件，iotUrl-->{}", iotUrl);
                    //找不到的的则为页面新增的直接备份即可
                    if ( !fileUrl.contains( gkUrl ) ){
                        log.info("备份新增的物联附件，fileUrl-->{}", fileUrl);
                        dvAttachmentService.syncWlFile( deviceNoId, AttachmentTypeEnum.devicePicture.name(), fileUrl, null, type );
                    }
                }
            }
        } catch (Exception e) {
            log.error("附件备份数据失败: {}", e);
        }

    }
}
